"""监控进程模块 - 持续采集功耗数据"""

from __future__ import annotations

import time
from typing import Any, Optional
from multiprocessing.synchronize import Barrier as BarrierType, Event as EventType
from multiprocessing.managers import ListProxy


def monitor_worker(
    barrier: BarrierType,
    event_list: list[EventType],
    power_samples: ListProxy,
    device_id: int = 0,
    sample_rate_hz: float = 50.0,
    power_backend: Optional[str] = None
):
    """
    监控进程工作函数 - 持续运行，复用于所有模型测试
    
    Args:
        barrier: 三进程同步屏障
        event_list: 事件列表
            [0]: model_infer_stop_event - 推理完成信号
            [1]: data_copy_completed_event - 数据复制完成信号  
            [2]: monitor_stop_event - 全局退出信号
            [3]: power_data_ready_event - 功耗数据就绪信号（复制完成后设置）
        power_samples: 共享列表，存储功耗采样数据 (timestamp_ms, power_mW)
        device_id: 设备ID
        sample_rate_hz: 采样频率
        power_backend: 功耗后端名称（None表示自动检测）
    """
    from ..metrics.power import PowerSampler
    
    # 创建功耗采样器
    try:
        power_sampler = PowerSampler(
            backend_name=power_backend,
            device_id=device_id,
            sample_rate_hz=sample_rate_hz
        )
        print(f"[Monitor] Power sampler initialized: backend={power_sampler.backend.get_name()}, device_id={device_id}, rate={sample_rate_hz}Hz")
    except Exception as e:
        print(f"[Monitor] Failed to initialize power sampler: {e}")
        # 如果初始化失败，继续运行但不会采集数据
        power_sampler = None
    
    while True:
        # 等待三进程同步（推理进程、监控进程、数据处理进程）
        barrier.wait()
        
        # 清空上一轮的功耗数据
        power_samples[:] = []
        
        # 如果没有采样器（初始化失败），跳过采样
        if power_sampler is None:
            # 等待推理完成信号（但不同步功耗数据）
            event_list[0].wait()
            # 即使没有数据，也设置就绪信号，避免数据处理进程一直等待
            event_list[3].set()
            event_list[0].clear()
            if event_list[2].is_set():
                break
            continue
        
        # 使用上下文管理器自动管理采样生命周期
        with power_sampler.sampling():
            # 立即进行一次采样（不等待 interval），确保至少有一个样本
            # 这样可以捕获到初始功耗状态
            power_mW = power_sampler.backend.sample()
            if power_mW is not None:
                power_sampler.samples.append((0.0, power_mW))
            
            # 等待推理完成信号（此时采样线程已在后台持续采样）
            event_list[0].wait()
        # with 块结束时自动停止采样
        
        # 在等待推理完成信号后，立即复制数据到共享列表
        # 必须在数据处理进程读取之前完成复制，避免竞态条件
        num_samples = len(power_sampler.samples)
        
        # 清空并复制数据（原子操作，避免中间状态）
        power_samples[:] = []  # 先清空
        # 批量复制所有样本
        samples_list = list(power_sampler.samples)  # 先转换为普通列表
        power_samples.extend(samples_list)  # 使用 extend 而不是逐个 append，更快且更原子
        
        # 设置功耗数据就绪信号，通知数据处理进程可以读取了
        event_list[3].set()  # 数据复制完成，通知数据处理进程
        
        # 注意：打印工作交给数据处理进程统一处理，避免输出混乱
        
        # 检查全局退出信号
        if event_list[2].is_set():
            break
        
        # 重置推理完成事件，准备下一轮
        event_list[0].clear()

